//
// Created by HP on 2025/11/16.
//

#include "Ticket.h"

std::string TypeOfTicket::HIGHSPEEDTRAINFirstClass = "HighFirstClass";
std::string TypeOfTicket::HIGHSPEEDTRAINSecondClass = "HighSecondClass";

std::string TypeOfTicket::QUICKSPEEDTRAINFirstClass = "QuickFirstClass";
std::string TypeOfTicket::QUICKSPEEDTRAINSecondClass = "QuickSecondClass";

std::string TypeOfTicket::NORMALLQUICKTRAINSoftBed = "SoftBed";
std::string TypeOfTicket::NORMALLQUICKTRAINHardBed = "HardBed";
std::string TypeOfTicket::NORMALLQUICKTRAINSoftSeat = "SoftSeat";
std::string TypeOfTicket::NORMALLQUICKTRAINHardSeat = "HardSeat";
std::string TypeOfTicket::NORMALLQUICKTRAINNoSeat = "NoSeat";

std::string TypeOfTicket::PLANEFirstClass = "FlyFirstClass";
std::string TypeOfTicket::PLANEEconomyClass = "FlyEconomyClass";

std::string TypeOfTicket::CARSeat = "CarSeat";

Ticket::Ticket() : Model("tickets"), cnt(0){
    this->type = TypeOfTicket::HIGHSPEEDTRAINSecondClass;
    setTableDefault("trainId", "VARCHAR(50) NOT NULL");
    setTableDefault("name", "VARCHAR(50) NOT NULL");
    setTableDefault("`from`", "VARCHAR(50) NOT NULL");
    setTableDefault("`to`", "VARCHAR(50) NOT NULL");
    setTableDefault("cnt", "INT NOT NULL");
    setTableDefault("price", "VARCHAR(50) NOT NULL");
    setTableDefault("startTime", "VARCHAR(50) NOT NULL");
    setTableDefault("endTime", "VARCHAR(50) NOT NULL");
    setTableDefault("type", "VARCHAR(50) NOT NULL DEFAULT '"+this->type+"'");
    setTableDefault("createdAt", "DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP");
}

void Ticket::bind(const std::string &key, const std::string &value) {
    if (!TableCols.count(key)) {
        std::cerr << "Error: Invalid key for user bind" << std::endl;
        return;
    }
    if (TableCols[key].find("UNIQUE")== std::string::npos&&key!="id") {
        std::cerr << "Error: Key is not unique for user bind" << std::endl;
        return;
    }

    std::string selectSql = "SELECT * FROM " + TableName + " WHERE " + key + " = '" + Model::escapeSqlLiteral(value) + "'" + ";";

    std::vector<std::map<std::string, std::string>> result = DBConnector::getInstance()->query(selectSql);

    if (result.empty()) {
        std::cerr << "init database failed: SQL execution error or no result. SQL: " << selectSql << std::endl;
        return;
    }

    std::cout << "bind success. Table: " << TableName << std::endl;

    if(result.size() > 1) {
        std::cerr << "Error: Multiple users found with the same " << key << std::endl;
        return;
    } else {
        this->id = result[0]["id"];
        this->trainId = result[0]["trainId"];
        this->name = result[0]["name"];
        this->from = result[0]["from"];
        this->to = result[0]["to"];
        this->cnt = std::stoi(result[0]["cnt"]);
        this->price = result[0]["price"];
        this->startTime = result[0]["startTime"];
        this->endTime = result[0]["endTime"];
        this->CreatedAt = result[0]["createdAt"];
        this->type = result[0]["type"];
    }
}

bool Ticket::save() {
    std::string createTicketSql = "INSERT INTO " + TableName + " (name, trainId ,`from`, `to`, cnt, price, startTime, endTime, type) VALUES ('"
                                  + Model::escapeSqlLiteral(name) + "', '"
                                  + Model::escapeSqlLiteral(trainId) + "', '"
                                  + Model::escapeSqlLiteral(from) + "', '"
                                  + Model::escapeSqlLiteral(to) + "', "
                                  + std::to_string(cnt) + ", '"
                                  + Model::escapeSqlLiteral(price) + "', '"
                                  + Model::escapeSqlLiteral(startTime) + "', '"
                                  + Model::escapeSqlLiteral(endTime) + "', '"
                                  + Model::escapeSqlLiteral(type) + "');";
    int executeCode = DBConnector::getInstance()->execute(createTicketSql);
    if (executeCode == -1) {
        std::cerr << "create ticket failed: SQL execution error. SQL: " << createTicketSql << std::endl;
        return false;
    } else {
        std::cout << "create ticket success. Table: " << TableName << std::endl;

        // 获得id
        std::string Sql = "SELECT LAST_INSERT_ID();";
        std::vector<std::map<std::string, std::string>> result = DBConnector::getInstance()->query(Sql);
        if (result.empty()) {
            std::cerr << "init database failed: SQL execution error or no result. SQL: " << Sql << std::endl;
            return false;
        }
        this->id = result[0]["LAST_INSERT_ID()"];
        std::cout<<"ticket id: "<<this->id<<std::endl;
        return true;
    }
}
